package v1

import (
	"encoding/csv"
	"os"
	"strconv"
	"time"
	"wms/internal/model"
	"wms/internal/model/request"
	"wms/internal/model/response"
	"wms/internal/service"
	"wms/pkg/common"
	"wms/pkg/global"
	"wms/pkg/logger"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

// LogController 日志控制器
type LogController struct {
	logService *service.LogService
}

// NewLogController 创建日志控制器
func NewLogController() *LogController {
	return &LogController{
		logService: service.NewLogService(),
	}
}

// GetLogList godoc
// @Summary 获取系统日志列表
// @Description 获取系统操作日志列表，支持分页、类型筛选和关键词搜索
// @Tags 系统管理
// @Accept json
// @Produce json
// @Security Bearer
// @Param page query int false "页码" default(1)
// @Param pageSize query int false "每页数量" default(10)
// @Param keyword query string false "搜索关键词"
// @Param type query string false "日志类型"
// @Param dateRange query []string false "日期范围，格式: ['2023-01-01', '2023-12-31']"
// @Success 200 {object} common.Response{data=[]response.LogResponse} "成功"
// @Failure 400 {object} common.Response "请求参数错误"
// @Failure 500 {object} common.Response "服务器内部错误"
// @Router /logs/list [get]
func (c *LogController) GetLogList(ctx *gin.Context) {
	var req request.LogListRequest

	// 尝试绑定JSON和Query参数
	if err := ctx.ShouldBindQuery(&req); err != nil {
		logger.Warn("绑定日志列表请求参数失败(Query)", zap.Error(err))
		// 尝试从JSON绑定
		if err := ctx.ShouldBindJSON(&req); err != nil {
			logger.Warn("绑定日志列表请求参数失败(JSON)", zap.Error(err))
			common.Error(ctx, err)
			return
		}
	}

	// 设置默认值
	if req.Page <= 0 {
		req.Page = 1
	}
	if req.PageSize <= 0 {
		req.PageSize = 10
	}

	logger.Info("开始获取日志列表",
		zap.Int("page", req.Page),
		zap.Int("pageSize", req.PageSize),
		zap.String("type", req.Type),
		zap.String("keyword", req.Keyword))

	logs, total, err := c.logService.GetLogs(req)
	if err != nil {
		logger.Error("获取日志列表失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	logger.Info("获取日志列表成功", zap.Int("count", len(logs)), zap.Int64("total", total))
	common.Success(ctx, gin.H{
		"list":  logs,
		"total": total,
		"page":  req.Page,
		"size":  req.PageSize,
	})
}

// GetLogTypes godoc
// @Summary 获取日志类型列表
// @Description 获取系统中所有可用的日志类型
// @Tags 系统管理
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {object} common.Response{data=response.LogTypesResponse} "成功"
// @Failure 500 {object} common.Response "服务器内部错误"
// @Router /logs/types [get]
func (c *LogController) GetLogTypes(ctx *gin.Context) {
	// 返回预定义的日志类型
	logTypes := c.logService.GetLogTypes()
	common.Success(ctx, response.LogTypesResponse{Types: logTypes})
}

// ExportLogs godoc
// @Summary 导出系统日志
// @Description 将系统日志导出为文件下载
// @Tags 系统管理
// @Accept json
// @Produce octet-stream
// @Security Bearer
// @Param page query int false "页码" default(1)
// @Param pageSize query int false "每页数量" default(10)
// @Param keyword query string false "搜索关键词"
// @Param type query string false "日志类型"
// @Param dateRange query []string false "日期范围，格式: ['2023-01-01', '2023-12-31']"
// @Success 200 {file} file "日志导出文件"
// @Failure 400 {object} common.Response "请求参数错误"
// @Failure 500 {object} common.Response "服务器内部错误"
// @Router /logs/export [get]
func (c *LogController) ExportLogs(ctx *gin.Context) {
	var req request.LogListRequest
	if err := ctx.ShouldBindQuery(&req); err != nil {
		logger.Warn("绑定日志导出请求参数失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	// 使用更大的页面大小获取更多日志数据
	req.PageSize = 1000
	logs, _, err := c.logService.GetLogs(req)
	if err != nil {
		logger.Error("获取导出日志数据失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	if len(logs) == 0 {
		ctx.JSON(400, gin.H{"code": 400, "message": "没有数据可导出"})
		return
	}

	// 创建临时CSV文件
	fileName := "logs_" + time.Now().Format("20060102150405") + ".csv"
	file, err := os.Create(fileName)
	if err != nil {
		logger.Error("创建导出文件失败", zap.Error(err))
		ctx.JSON(500, gin.H{"code": 500, "message": "创建导出文件失败"})
		return
	}
	defer file.Close()

	// 创建CSV写入器
	writer := csv.NewWriter(file)
	defer writer.Flush()

	// 写入CSV头
	headers := []string{"ID", "用户ID", "用户名", "IP地址", "操作类型", "请求方法", "请求路径", "状态码", "耗时(ms)", "创建时间"}
	if err := writer.Write(headers); err != nil {
		logger.Error("写入CSV头失败", zap.Error(err))
		ctx.JSON(500, gin.H{"code": 500, "message": "写入导出文件失败"})
		return
	}

	// 写入数据行
	for _, log := range logs {
		record := []string{
			strconv.Itoa(int(log.ID)),
			strconv.Itoa(int(log.UserID)),
			log.Username,
			log.IP,
			log.Type,
			log.Method,
			log.Path,
			strconv.Itoa(log.Status),
			strconv.FormatInt(log.Latency, 10),
			log.CreatedAt.Format("2006-01-02 15:04:05"),
		}
		if err := writer.Write(record); err != nil {
			logger.Error("写入CSV数据行失败", zap.Error(err))
			continue
		}
	}

	// 设置响应头
	ctx.Header("Content-Description", "File Transfer")
	ctx.Header("Content-Disposition", "attachment; filename="+fileName)
	ctx.Header("Content-Type", "text/csv")
	ctx.File(fileName)

	// 删除临时文件
	go func() {
		time.Sleep(time.Second * 5)
		os.Remove(fileName)
	}()
}

// ClearLogs godoc
// @Summary 清空系统日志
// @Description 清空系统中所有操作日志（谨慎使用）
// @Tags 系统管理
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {object} common.Response "清空成功"
// @Failure 500 {object} common.Response "服务器内部错误"
// @Router /logs/clear [delete]
func (c *LogController) ClearLogs(ctx *gin.Context) {
	// 清空日志功能实现
	result := global.DB.Delete(&model.OperationLog{}, "id > ?", 0)
	if result.Error != nil {
		logger.Error("清空日志失败", zap.Error(result.Error))
		ctx.JSON(500, gin.H{"code": 500, "message": "清空日志失败: " + result.Error.Error()})
		return
	}

	common.Success(ctx, gin.H{
		"message": "清空日志成功",
		"count":   result.RowsAffected,
	})
}
